import styles from './index.module.less';
import Workspace, { ChildType, IFileInfo } from '@/pages/CodeEditor/workspace';
import FileItemView from './FileItemView';
import { IIFileInfo2 } from '.';

export class ExplorerLogic {
  private _open_keys = new Set('');
  private _workspace_name: string = '';
  private _div: HTMLDivElement | null = null;
  async workspace() {
    return Workspace.get(this._workspace_name);
  }
  set_workspace_name(name: string): void {
    this._workspace_name = name;
  }
  set_div(current: HTMLDivElement | null) {
    this._div = current;
    this.render();
  }
  private _tending_drop_to(id: string) {
  }
  private async _render_list_item(workspace: Workspace, list_div: HTMLElement, info: IIFileInfo2, remains: FileItemView[]): Promise<number> {
    let count = 1;
    const { id, type, name, depth, parent_id } = info;
    let item_div: FileItemView;
    if (remains.length) {
      item_div = remains.shift()!;
    } else {
      item_div = FileItemView.create();
      item_div.className = styles.workspace_list_item;
      list_div.append(item_div);
    }
    item_div.parent_id = parent_id;
    item_div.id = id;
    item_div.type = type;
    item_div.name = name;
    item_div.depth = depth;
    item_div.ondragover = e => {
      e.preventDefault();
      return false;
    };
    item_div.ondragenter = (e) => {
      const target = FileItemView.fromEvent(e);
      if (!target) return;
      const f_id = e.dataTransfer?.getData("f_id");
      const f_parent_id = e.dataTransfer?.getData("f_parent_id");
      if (f_id === target.id || f_parent_id === target.id) return;

      console.log('ondragenter', target.name);

      const dist_id = target.type === ChildType.File ? target.parent_id : target.id;
      this._tending_drop_to(dist_id);
      e.preventDefault();
    };

    item_div.ondragleave = (e: DragEvent) => {
      const target = FileItemView.fromEvent(e);
      if (!target) return;
      const f_id = e.dataTransfer?.getData("f_id");
      const f_parent_id = e.dataTransfer?.getData("f_parent_id");
      if (f_id === target.id || f_parent_id === target.id) return;

      console.log('ondragleave', target.name);
      e.preventDefault();
    };

    item_div.ondrop = async (e: DragEvent) => {
      const target = FileItemView.fromEvent(e);
      if (!target) return;

      // 当前目录的ID
      const dist_dir_id = target.type === ChildType.File ? target.parent_id : target.id;

      // 被拖动的对象的ID
      const dragging_id = e.dataTransfer?.getData("f_id");

      // 被拖动的对象所在的目录ID
      const old_parent_id = e.dataTransfer?.getData("f_parent_id");

      if (typeof dragging_id !== 'string' || typeof old_parent_id !== 'string')
        return;

      if (old_parent_id === dist_dir_id)
        return console.log("已经在此目录下");


      await workspace.move(dragging_id, dist_dir_id);
      this.render();
    };
    item_div.ondragstart = (e) => {
      const target = FileItemView.fromEvent(e);
      if (!target) return;
      e.dataTransfer?.setData("f_id", id);
      e.dataTransfer?.setData("f_name", name);
      e.dataTransfer?.setData("f_parent_id", parent_id);
      console.log('ondragstart', target.name);
    };
    item_div.ondragend = (e) => {
      const target = FileItemView.fromEvent(e);
      if (!target) return;
      console.log('ondragend', target.name);
    };
    if (type === ChildType.Dir) {
      const open = this._open_keys.has(id);
      item_div.open = open;
      item_div.onclick = () => this._toggle_folder(id);
      if (open) {
        const list = await workspace.list(id);
        for (const item of list) {
          const info: IIFileInfo2 = { ...item, depth: depth + 1 };
          count += await this._render_list_item(workspace, list_div, info, remains);
        }
      }
    } else {
      item_div.onclick = () => this._open_file(id);
    }
    item_div.on_rename = (name) => {
      workspace.rename(id, name)
        .finally(() => this.render());
    };
    return count;
  }
  on_file_open = (info: IFileInfo, content: string) => { };
  private _open_file = async (id: string) => {
    const workspace = await this.workspace();
    const info = await workspace.info(id);
    const content = await workspace.load_file(id);
    this.on_file_open?.(info, content);
  };
  private _toggle_folder = async (id: string) => {
    const m = this._open_keys.has(id) ? 'delete' : 'add';
    this._open_keys[m](id);
    this.render();
  };
  async render() {
    const list_div = this._div;
    if (!list_div) return console.warn('[FileListLogic] nothings render!');
    const workspace = await this.workspace();
    const vitual_info: IIFileInfo2 = { id: '', parent_id: '!', depth: 0, name: this._workspace_name, type: ChildType.Dir };
    const old_children = Array.from(list_div.children) as FileItemView[];
    const count = await this._render_list_item(workspace, list_div, vitual_info, old_children);
    const new_children = Array.from(list_div.children);
    if (new_children.length > count) {
      for (let i = count; i < new_children.length; ++i) {
        new_children[i].remove();
      }
    }
  }
}
